home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-09 | 13.3 KB | 714 lines | [TEXT/CWIE] |
- //
- // ViewerTest.c
- //
- // Theron's first QuickDraw 3D program
- //
- // A simple QD3D Viewer application. Allows the user to open a 3DMF file
- // and display the object in it using the standard QD3D viewer.
- //
- // Much of this was taken from two books:
- // 3D Graphics Programming With QuickDraw 3D (Apple's QD3D book)
- // Tricks of The Mac Game Programming Gurus
- // With much coming from Inside Macintosh and The Mac C Programming Primer
- //
- // Version 0.1
- //
- // The following libraries are included in the CW7 project:
- // InterfaceLib
- // QuickDraw3DAcceleratorLib
- // QuickDraw3DLib
- // QuickDraw3DViewerLib (must be imported "weak")
- // MathLib
- // MWCRuntime.Lib
- //
- // For all I know, not all of these are neccessary...
-
-
- #include <Gestalt.h>
- #include <CodeFragments.h>
- #include <Dialogs.h>
-
- // and all of the QD3D header files, just in case...
- #include <QD3d.h>
- #include <QD3DAcceleration.h>
- #include <QD3DCamera.h>
- #include <QD3DController.h>
- #include <QD3DDrawContext.h>
- #include <QD3DErrors.h>
- #include <QD3DGeometry.h>
- #include <QD3DGroup.h>
- #include <QD3DIO.h>
- #include <QD3DLight.h>
- #include <QD3DMath.h>
- #include <QD3DPick.h>
- #include <QD3DRenderer.h>
- #include <QD3DSet.h>
- #include <QD3DShader.h>
- #include <QD3DStorage.h>
- #include <QD3DString.h>
- #include <QD3DStyle.h>
- #include <QD3DTransform.h>
- #include <QD3DView.h>
- #include <QD3DViewer.h>
-
-
- //
- // Constants
- //
- #define kNilFilterProc nil
- #define kEmptyString "\p"
- #define kSleep 32767
- #define kMoveToFront (WindowPtr)-1L
-
- #define kBaseResID 700
- #define kErrorResID kBaseResID
- #define kAboutResID kBaseResID
-
- #define mApple kBaseResID + 0
- #define iAbout 1
-
- #define mFile kBaseResID + 1
- #define iOpen 1
- #define iClose 2
- // item 3 is a separator
- #define iQuit 4
-
- #define mEdit kBaseResID + 2
- #define iUndo 1
- // item 2 is a separator
- #define iCut 3
- #define iCopy 4
- #define iPaste 5
- #define iClear 6
-
-
- //
- // Global Variables
- //
- Boolean gDone, gWindowOpen, gFileOpen, gViewerActive;
- WindowPtr gWindow;
- short gOpenFileRefNum;
- TQ3ViewerObject gViewer;
-
-
- //
- // Prototypes
- //
- void ToolBoxInit( void );
- void MenuBarInit( void );
- void MainLoop( void );
- void DoEvent( EventRecord *eventPtr );
- void DoUpdate( EventRecord *eventPtr );
- void HandleMouseDown( EventRecord *eventPtr );
- void HandleMenuChoice( long menuChoice );
- void SetFileMenuStuff( void );
- void SetEditMenuStuff( void );
- void HandleAppleChoice( short item );
- void ShowAboutBox( void );
- void HandleFileChoice( short item );
- void Open3DMFFile( void );
- void Close3DMFFile( void );
- Boolean MyEnvironmentHas3DViewer( void );
- Boolean CheckGestaltFor3D( void );
- void DisplayFatalError( Str255 errorString );
- void DisplayAlert( Str255 errorString );
- void OpenMyWindow( Str255 windowTitle );
- void CloseMyWindow( void );
- void CreateViewerInWindow( void );
- TQ3ViewerObject MyCreateViewer( WindowPtr myWindow );
-
-
- //
- // The Routines
- //
-
-
- //
- // ToolBoxInit
- //
- void ToolBoxInit( void )
- {
- InitGraf( &qd.thePort );
- /* InitGraf( &thePort ); */ // This is how it's done in Think C...
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs( nil );
- InitCursor();
- }
-
-
- //
- // MenuBarInit
- //
- void MenuBarInit( void )
- {
- Handle menuBar;
- MenuHandle menu;
- OSErr myErr;
-
- menuBar = GetNewMBar( kBaseResID ); // load the menubar resource
- if ( menuBar == nil )
- DisplayFatalError( "\pERROR: could not load menu resource!" );
-
- SetMenuBar( menuBar ); // make it the current menubar
-
- menu = GetMHandle( mApple ); // get a handle to the apple menu
- AddResMenu( menu, 'DRVR' ); // add the desk accessories to the Apple menu
-
- DrawMenuBar(); // draw the menu bar
- }
-
-
- // MainLoop
- //
- void MainLoop( void )
- {
- EventRecord event;
- Boolean isViewerEvent;
-
- gDone = false;
- while ( gDone == false )
- {
- if ( WaitNextEvent( everyEvent, &event, kSleep, nil ) )
- {
- // Let the 3D viewer handle the event if it should:
- if ( Q3ViewerEvent( gViewer, &event ) == false )
- DoEvent( &event ); // Otherwise, it's my responsibility
- }
- }
- }
-
-
- //
- // DoEvent
- //
- void DoEvent( EventRecord *eventPtr )
- {
- char theChar;
-
- switch ( eventPtr->what )
- {
- case kHighLevelEvent:
- break;
- case mouseDown:
- HandleMouseDown( eventPtr );
- break;
- case mouseUp:
- // No real need for mouseUp events...
- break;
- case keyDown:
- case autoKey:
- theChar = eventPtr->message & charCodeMask;
- if ( (eventPtr->modifiers & cmdKey) != 0)
- HandleMenuChoice( MenuKey( theChar ) );
- break;
- case keyUp:
- // No real need for keyUp events...
- break;
- case updateEvt:
- DoUpdate( eventPtr );
- break;
- case diskEvt:
- break;
- case activateEvt:
- break;
- case networkEvt:
- break;
- case driverEvt:
- break;
- case app1Evt:
- break;
- case app2Evt:
- break;
- case app3Evt:
- break;
- case osEvt:
- break;
- }
- }
-
-
- //
- // DoUpdate
- //
- void DoUpdate( EventRecord *eventPtr )
- {
- WindowPtr window;
-
- window = (WindowPtr) eventPtr->message;
-
- BeginUpdate( window );
-
- // Do any update-specific tasks here
- // Right now, it's just a dummy thing so the program doesn't
- // screech to a grinding halt when something covers the
- // window...
-
- EndUpdate( window );
- }
-
-
- //
- // HandleMouseDown
- //
- void HandleMouseDown( EventRecord *eventPtr )
- {
- WindowPtr window;
- short thePart;
- long menuChoice;
- Boolean windowGoAway;
-
- thePart = FindWindow( eventPtr->where, &window );
-
- switch ( thePart )
- {
- case inMenuBar:
- menuChoice = MenuSelect( eventPtr->where ); // do the menu thing
- HandleMenuChoice( menuChoice );
- break;
- case inSysWindow:
- SystemClick( eventPtr, window );
- break;
- case inContent:
- // I may not need this, because I will only have one window...
- break;
- case inDrag:
- DragWindow( window, eventPtr->where, &qd.screenBits.bounds );
- // In Think C or Symantec C++, the following would work:
- // DragWindow( window, eventPtr->where, &screenBits.bounds );
- Q3ViewerSetBounds( gViewer, &(window->portRect) );
- Q3ViewerDraw( gViewer );
- break;
- case inGoAway:
- windowGoAway = TrackGoAway( window, eventPtr->where );
- if ( windowGoAway )
- {
- Close3DMFFile();
- }
- break;
- }
- }
-
-
- //
- // HandleMenuChoice
- //
- void HandleMenuChoice( long menuChoice )
- {
- short menu;
- short item;
-
- if ( menuChoice != 0 )
- {
- menu = HiWord( menuChoice );
- item = LoWord( menuChoice );
-
- switch ( menu )
- {
- case mApple:
- HandleAppleChoice( item );
- break;
- case mFile:
- HandleFileChoice( item );
- break;
- case mEdit:
-
- break;
- }
- HiliteMenu( 0 );
- }
- }
-
-
- //
- // SetFileMenuStuff
- //
- void SetFileMenuStuff( void )
- {
- MenuHandle myMenu;
-
- myMenu = GetMenuHandle( mFile );
-
- if ( gWindowOpen )
- EnableItem( myMenu, iClose );
- else
- DisableItem( myMenu, iClose );
- }
-
-
- //
- // SetEditMenuStuff
- //
- void SetEditMenuStuff( void )
- {
- MenuHandle myMenu;
-
- myMenu = GetMenuHandle( mEdit );
-
- DisableItem( myMenu, iUndo );
- DisableItem( myMenu, iCut );
- DisableItem( myMenu, iCopy );
- DisableItem( myMenu, iPaste );
- DisableItem( myMenu, iClear );
- }
-
-
- //
- // HandleAppleChoice
- //
- void HandleAppleChoice( short item )
- {
- MenuHandle appleMenu;
- Str255 accName;
- short accNumber;
-
- switch ( item )
- {
- case iAbout:
- ShowAboutBox();
- break;
- default:
- appleMenu = GetMHandle( mApple );
- GetItem( appleMenu, item, accName );
- accNumber = OpenDeskAcc( accName );
- break;
- }
- }
-
-
- //
- // ShowAboutBox
- //
- void ShowAboutBox( void )
- {
- DialogPtr myDialog;
-
- myDialog = GetNewDialog( kAboutResID, nil, kMoveToFront );
- ShowWindow( myDialog );
- DrawDialog( myDialog );
-
- /* Wait until the user releases the mouse button.
- * If the user holds down the mouse when a click causes a message to be displayed,
- * we must wait until they release the button before checking for a click (see below)
- * to clear the dialog - so they at least have a chance to see it.
- * NOTE THE SEMICOLON!
- * This is a loop which waits until the mouse button is not down.
- */
- while ( Button() );
-
- /* Now, wait until the user clicks:
- * NOTE THE SEMICOLON!
- * This is a loop which waits until the mouse is clicked.
- */
- while ( ! Button() );
-
- /* clear the event queue so the click doesn't do anything: */
- FlushEvents( everyEvent, 0 );
-
- DisposeDialog( myDialog ); /* Get rid of the dialog */
- }
-
-
- //
- // HandleFileChoice
- //
- void HandleFileChoice( short item )
- {
- switch ( item )
- {
- case iOpen:
- Open3DMFFile();
- // This will have to do much more...
- // Put up open file dialog box
- // Open the file
- // Pass it to the viewer
- //
- // This is only temporary, to make it do something:
- // OpenMyWindow();
- break;
- case iClose:
- Close3DMFFile();
- break;
- case iQuit:
- Close3DMFFile(); // Close the window if it's open
- gDone = true;
- break;
- }
- }
-
-
- //
- // Open3DMFFile
- //
- void Open3DMFFile( void )
- {
- StandardFileReply myReply;
- FSSpec mySpec;
- SFTypeList myTypes;
- OSErr myErr;
- short myFileRefNum;
-
- // Open only 3DMF files
- myTypes[0] = '3DMF';
-
- // Put up the standard get file dialog box
- StandardGetFile( nil, 1, myTypes, &myReply );
-
- if ( myReply.sfGood ) // User hit Open...
- {
- // If there's already a file open, close it:
- Close3DMFFile();
-
- // Open the new file:
- mySpec = myReply.sfFile;
- myErr = FSpOpenDF( &mySpec, fsRdWrPerm, &myFileRefNum );
- if ( myErr != noErr )
- {
- DisplayAlert( "\pERROR: could not open file" );
- }
- else
- {
- gFileOpen = true;
- gOpenFileRefNum = myFileRefNum;
- OpenMyWindow( mySpec.name );
- // Now, create a viewer in the window
- CreateViewerInWindow();
- Q3ViewerUseFile( gViewer, gOpenFileRefNum );
- }
- }
- }
-
- void Close3DMFFile( void )
- {
- OSErr myErr;
-
- if ( gFileOpen )
- {
- // Dispose of the viewer:
- if ( gViewerActive )
- {
- myErr = Q3ViewerDispose( gViewer );
- if ( myErr != noErr )
- DisplayAlert( "\pERROR: could not dispose of viewer" );
- else
- gViewerActive = false;
- }
-
- // Close the window
- if ( gWindowOpen )
- {
- CloseMyWindow(); // Close the current window
- }
-
- // Close the file
- if ( gFileOpen )
- {
- myErr = FSClose( gOpenFileRefNum );
- if ( myErr != noErr )
- DisplayAlert( "\pERROR: could not close file" );
- else
- gFileOpen = false;
- }
- }
- }
-
-
- //
- // MyEnvironmentHas3DViewer
- // For this routine to work, we have to establish a
- // "weak" link to the QuickDraw3DViewerLib library.
- //
- Boolean MyEnvironmentHas3DViewer( void )
- {
- return((Boolean)Q3ViewerNew != kUnresolvedSymbolAddress);
- }
-
-
- //
- // CheckGestaltFor3D
- //
- Boolean CheckGestaltFor3D( void )
- {
- OSErr err;
- long feature;
-
- err = Gestalt( gestaltQD3DViewer, &feature );
-
- if ( err != noErr )
- {
- return false;
- }
- else
- {
- if ( feature == gestaltQD3DViewerAvailable )
- return true;
- else
- return false;
- }
- }
-
-
- //
- // DisplayFatalError
- // Display a stop alert box with a single text string, then quit
- void DisplayFatalError( Str255 errorString )
- {
- ParamText( errorString, kEmptyString, kEmptyString, kEmptyString );
- StopAlert( kErrorResID, kNilFilterProc );
- ExitToShell();
- }
-
-
- //
- // DisplayAlert
- //
- void DisplayAlert( Str255 errorString )
- {
- ParamText( errorString, kEmptyString, kEmptyString, kEmptyString );
- StopAlert( kErrorResID, kNilFilterProc );
- }
-
-
- //
- // OpenMyWindow
- //
- void OpenMyWindow( Str255 windowTitle )
- {
- WindowPtr tempWindow;
-
- if ( gWindowOpen )
- {
- CloseMyWindow(); // Close the current window
- }
-
- tempWindow = GetNewCWindow( kBaseResID, nil, kMoveToFront );
-
- if ( tempWindow == nil )
- DisplayFatalError( "\pERROR: could not open the window" );
-
- gWindow = tempWindow;
- gWindowOpen = true;
-
- SetPort( gWindow ); // Draw IN the window!
- SetWTitle( gWindow, windowTitle ); // Set the window's name
-
- ShowWindow( gWindow );
-
- SetFileMenuStuff();
- }
-
-
- //
- // CloseMyWindow
- //
- void CloseMyWindow( void )
- {
- if ( gWindowOpen ) // Just to be sure...
- {
- DisposeWindow( gWindow );
- gWindowOpen = false;
- }
-
- SetFileMenuStuff();
- }
-
-
- //
- // CreateViewerInWindow
- //
- void CreateViewerInWindow( void )
- {
- TQ3ViewerObject myViewer;
-
- if ( gWindowOpen )
- {
- myViewer = MyCreateViewer( gWindow );
-
- if ( myViewer == nil )
- DisplayAlert( "\pERROR: could not create viewer" );
- else
- {
- gViewer = myViewer;
- gViewerActive = true;
- }
- }
- }
-
-
- //
- // MyCreateViewer
- //
- TQ3ViewerObject MyCreateViewer( WindowPtr myWindow )
- {
- TQ3ViewerObject myViewer;
- Rect myRect;
- Point myTL, myBR;
-
- // Get rectangle enclosing the window's content region
- myRect = myWindow->portRect;
-
- if ( EmptyRect( &myRect ) )
- return( nil );
-
- // Create a new viewer object in entire content region
- myViewer = Q3ViewerNew( (CGrafPtr)myWindow, &myRect, kQ3ViewerDefault );
- if ( myViewer == nil )
- return( nil );
-
- Q3ViewerSetBounds( myViewer, &myRect );
-
- Q3ViewerDraw( myViewer );
-
- return( myViewer );
- }
-
-
- //
- // Main
- //
- void main( void )
- {
- TQ3Status myStatus;
-
- ToolBoxInit(); // Initialize toolbox managers
- MenuBarInit(); // Set up our menubar
-
- // Check Gestalt for QuickDraw 3D:
- if ( CheckGestaltFor3D() == true )
- {
- if ( MyEnvironmentHas3DViewer() != true )
- DisplayFatalError( "\pERROR: QuickDraw 3D Viewer not installed!" );
- }
- else
- DisplayFatalError( "\pERROR: QuickDraw 3D not installed!" );
-
- myStatus = Q3Initialize();
- if ( myStatus == kQ3Failure )
- DisplayFatalError( "\pERROR: Could not initialize QuickDraw 3D" );
-
- if ( Q3IsInitialized() == kQ3False )
- DisplayFatalError( "\pERROR: Could not initialize QuickDraw 3D" );
-
- gWindowOpen = false;
- gFileOpen = false;
- gViewerActive = false;
- SetFileMenuStuff();
- SetEditMenuStuff();
-
- ShowAboutBox();
-
- MainLoop(); // Go do the main even loop
-
- myStatus = Q3Exit();
- if ( myStatus == kQ3Failure )
- DisplayAlert( "\pERROR: could not unload QuickDraw 3D" );
- }
-
-
-
-
-
-
-